﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
using ExFlash.Tags;

namespace ExFlash.Records
{
    public enum FillStyleType : byte
    {
        SolidFill = 0x00,
        LinearGradientFill = 0x10,
        RadialGradientFill = 0x12,
        FocalRadialGradientFill = 0x13,
        RepeatingBitmapFill = 0x40,
        ClippedBitmapFill = 0x41,
        NonSmoothedRepeatingBitmap = 0x42,
        NonSmoothedClippedBitmap = 0x43
    }

    [TypeConverter(typeof(ExpandableObjectConverter))]
    public class FillStyleRecord : ISwfSerializable, IReferenceCharacterId
    {
        private readonly ShapeType _shapeType;
        
        public FillStyleType FillStyleType
        {
            get;
            private set;
        }

        public RGBRecord Color
        {
            get;
            private set;
        }

        public MatrixRecord GradientMatrix
        {
            get;
            private set;
        }

        public Gradient Gradient
        {
            get;
            private set;
        }
        
        public ushort BitmapId
        {
            get;
            private set;
        }

        public MatrixRecord BitmapMatrix
        {
            get;
            private set;
        }

        public FillStyleRecord(ShapeType type)
        {
            _shapeType = type;
        }

        //public virtual Brush GetBrush(GraphicsPath path)
        //{
        //    Brush brush;

        //    switch (FillStyleType)
        //    {
        //        case FillStyleType.SolidFill:
        //            {
        //                brush = new SolidBrush(Color.GetColor());
        //                break;
        //            }
        //        case FillStyleType.LinearGradientFill:
        //            {
        //                if (Gradient.NumGradients < 2)
        //                {
        //                    brush = new SolidBrush(Color.GetColor());
        //                    break;
        //                }

        //                LinearGradientBrush linearBrush = new LinearGradientBrush(path.GetBounds(),
        //                    Gradient.GradientRecords[0].Color.GetColor(),
        //                    Gradient.GradientRecords[1].Color.GetColor(),
        //                    LinearGradientMode.Horizontal);

        //                if (Gradient.NumGradients > 2)
        //                {
        //                    linearBrush.InterpolationColors = new ColorBlend(Gradient.NumGradients);

        //                    Color[] colors = new Color[Gradient.NumGradients];
        //                    float[] ratios = new float[Gradient.NumGradients];

        //                    for (int i = 0; i < Gradient.NumGradients; i++)
        //                    {
        //                        colors[i] = Gradient.GradientRecords[i].Color.GetColor();
        //                        ratios[i] = 255.0f / Gradient.GradientRecords[i].Ratio;
        //                    }

        //                    ratios[0] = 0.0f;
        //                    ratios[Gradient.NumGradients - 1] = 1.0f;

        //                    linearBrush.InterpolationColors.Colors = colors;
        //                    linearBrush.InterpolationColors.Positions = ratios;
        //                }

        //                linearBrush.Transform = (Matrix)GradientMatrix;
        //                linearBrush.WrapMode = WrapMode.Tile;

        //                brush = linearBrush;
        //                break;
        //            }
        //        case FillStyleType.RadialGradientFill:
        //            {
        //                PathGradientBrush pathBrush = new PathGradientBrush(path) {Transform = (Matrix) GradientMatrix};

        //                if (Gradient.NumGradients > 2)
        //                {
        //                    pathBrush.InterpolationColors = new ColorBlend(Gradient.NumGradients);

        //                    Color[] colors = new Color[Gradient.NumGradients];
        //                    float[] ratios = new float[Gradient.NumGradients];

        //                    for (int i = 0; i < Gradient.NumGradients; i++)
        //                    {
        //                        colors[i] = Gradient.GradientRecords[i].Color.GetColor();
        //                        ratios[i] = 255.0f / Gradient.GradientRecords[i].Ratio;
        //                    }

        //                    ratios[0] = 0.0f;
        //                    ratios[Gradient.NumGradients - 1] = 1.0f;

        //                    pathBrush.InterpolationColors.Colors = colors;
        //                    pathBrush.InterpolationColors.Positions = ratios;
        //                }
        //                else
        //                {
        //                    brush = new SolidBrush(Color.GetColor());
        //                    break;
        //                }

        //                brush = pathBrush;
        //                break;
        //            }
        //        case FillStyleType.FocalRadialGradientFill:
        //            {
        //                PathGradientBrush pathBrush = new PathGradientBrush(path) {Transform = (Matrix) GradientMatrix};

        //                if (Gradient.NumGradients > 2)
        //                {
        //                    pathBrush.InterpolationColors = new ColorBlend(Gradient.NumGradients);

        //                    Color[] colors = new Color[Gradient.NumGradients];
        //                    float[] ratios = new float[Gradient.NumGradients];

        //                    for (int i = 0; i < Gradient.NumGradients; i++)
        //                    {
        //                        colors[i] = Gradient.GradientRecords[i].Color.GetColor();
        //                        ratios[i] = 255.0f / Gradient.GradientRecords[i].Ratio;
        //                    }

        //                    ratios[0] = 0.0f;
        //                    ratios[Gradient.NumGradients - 1] = 1.0f;

        //                    pathBrush.InterpolationColors.Colors = colors;
        //                    pathBrush.InterpolationColors.Positions = ratios;
        //                }
        //                else
        //                {
        //                    brush = new SolidBrush(Color.GetColor());
        //                    break;
        //                }

        //                pathBrush.CenterPoint = new PointF((path.GetBounds().X + path.GetBounds().Width / 2.0f), (path.GetBounds().Y + path.GetBounds().Height / 2.0f));

        //                brush = pathBrush;
        //                break;
        //            }
        //        case FillStyleType.RepeatingBitmapFill:
        //        case FillStyleType.NonSmoothedRepeatingBitmap:
        //            {
        //                Tag tag;
        //                DefineBitsTag bitmapTag;

        //                if (!IdDictionary.Instance.Dictionary.TryGetValue(BitmapId, out tag))
        //                {
        //                    throw new Exception("Bitmap ID does not exist in Dictionary");
        //                }
                        
        //                if ((bitmapTag = tag as DefineBitsTag) == null)
        //                {
        //                    throw new Exception("ID exists in Dictionary but isn't an image");
        //                }

        //                Stream st = new MemoryStream(bitmapTag.ImageData);
                        
        //                brush = new TextureBrush(new Bitmap(st))
        //                            {Transform = (Matrix) BitmapMatrix, 
        //                                WrapMode = WrapMode.Tile};

        //                break;
        //            }
        //        case FillStyleType.ClippedBitmapFill:
        //        case FillStyleType.NonSmoothedClippedBitmap:
        //            {
        //                Tag tag;
        //                DefineBitsTag bitmapTag;

        //                if (!IdDictionary.Instance.Dictionary.TryGetValue(BitmapId,out tag))
        //                {
        //                    throw new Exception("Bitmap ID does not exist in Dictionary");
        //                }
                        
        //                if ((bitmapTag = tag as DefineBitsTag) == null)
        //                {
        //                    throw new Exception("ID exists in Dictionary but isn't an image");
        //                }

        //                Stream st = new MemoryStream(bitmapTag.ImageData);
                        
        //                brush = new TextureBrush(new Bitmap(st))
        //                        {Transform = (Matrix) BitmapMatrix, 
        //                            WrapMode = WrapMode.Clamp};

        //                break;
        //            }
        //        default:
        //            {
        //                throw new Exception("Unknown Fill type");
        //            }
        //    }

        //    return brush;
        //}

        #region ISwfSerializable Members

        public void SwfDeserialize(BinaryBitReader reader)
        {
            FillStyleType = (FillStyleType)reader.ReadByte();

            switch (FillStyleType)
            {
                case FillStyleType.SolidFill:
                    {
                        if (_shapeType == ShapeType.Shape1 || _shapeType == ShapeType.Shape2)
                        {
                            Color = new RGBRecord();
                        }
                        else
                        {
                            Color = new RGBARecord();
                        }

                        Color.SwfDeserialize(reader); 
                        break;
                    }
                case FillStyleType.LinearGradientFill:
                case FillStyleType.RadialGradientFill:
                    {
                        GradientMatrix = new MatrixRecord();
                        GradientMatrix.SwfDeserialize(reader);
                        Gradient = new Gradient(_shapeType);
                        Gradient.SwfDeserialize(reader); 
                        break;
                    }
                case FillStyleType.FocalRadialGradientFill:
                    {
                        GradientMatrix = new MatrixRecord();
                        GradientMatrix.SwfDeserialize(reader);
                        Gradient = new FocalGradient();
                        Gradient.SwfDeserialize(reader); 
                        break;
                    }
                case FillStyleType.RepeatingBitmapFill:
                case FillStyleType.ClippedBitmapFill:
                case FillStyleType.NonSmoothedRepeatingBitmap:
                case FillStyleType.NonSmoothedClippedBitmap:
                    {
                        BitmapId = reader.ReadUInt16();

                        BitmapMatrix = new MatrixRecord();
                        BitmapMatrix.SwfDeserialize(reader);
                        break;
                    }
                default:
                    {
                        throw new SerializationException("Error when deserializing FillStyle - Unknown FillStyleType.");
                    }
            }
        }

        public void SwfSerialize(byte[] arr, ref int offset)
        {
            throw new NotImplementedException();
        }

        #endregion

        public bool IsReferencing
        {
            get { return ((((int)FillStyleType) & 0xf0) == 0x40); }
        }

        public ushort ReferencedId
        {
            get { return BitmapId; }
        }

        public IEnumerable<Type> ReferencedAttributes
        {
            get { return new List<Type>(); }
        }
    }
}
